package genealogy.depricated.loaders;

import java.util.ArrayList;
import java.util.List;

import edu.byu.cs.dml.recordlinkage.pedigree.*;
import genealogy.deprecated.datamodel.pedigree.Gender;
import genealogy.deprecated.datamodel.pedigree.Individual;
import genealogy.deprecated.datamodel.pedigree.LifeEvent;
import genealogy.deprecated.datamodel.pedigree.PedigreeValidationError;
import genealogy.deprecated.datamodel.pedigree.RelationshipType;

/**
 * @author Steve
 * @invariant
 */
public class FhdIndividualConverter {

	/**
	 * @param ind1
	 * @return
	 * @pre
	 * @post
	 */
	public Individual convert(BaseIndividual fhdPedigree) {
		Individual pedigree = null;
		try
		{
			pedigree = createIndividual(fhdPedigree);
			addBaseIndividualItemsToIndividual(pedigree, fhdPedigree);

		} catch (PedigreeValidationError e)
		{
			e.printStackTrace();
		}
		return pedigree;
	}

	public void addBaseIndividualItemsToIndividual(Individual pedigree,
			BaseIndividual fhdPedigree) throws PedigreeValidationError {

		addEvent(pedigree, fhdPedigree.getBaptism(), "Baptism");
		addEvent(pedigree, fhdPedigree.getEndowment(), "Endowment");
		addEvent(pedigree, fhdPedigree.getSealingToParent(), "SealingToParent");

		addFather(pedigree, fhdPedigree.getFather());
		addMother(pedigree, fhdPedigree.getMother(), fhdPedigree
				.getMarriageOfParents());

		addSpouses(pedigree, fhdPedigree.getSpouses());
		addSiblings(pedigree, fhdPedigree.getSiblings());

		ArrayList<Child> children = fhdPedigree.getChildren();
		if (children != null)
		{
			for (Child child : children)
			{
				addChild(pedigree, child);
			}
		}
	}

	private void addMother(Individual pedigree, Parent mother,
			edu.byu.cs.dml.recordlinkage.pedigree.Event marriageOfParents) throws PedigreeValidationError {
		if (pedigree == null || mother == null)
		{
			return;
		}
		Individual motherToAdd = createIndividual(mother);
		motherToAdd.setRelationship(RelationshipType.MOTHER);
		motherToAdd.setGender(Gender.FEMALE);

		if (marriageOfParents != null)
		{
			addEvent(motherToAdd, marriageOfParents, "Marriage");
		}

		pedigree.addRelation(motherToAdd);
	}

	private void addFather(Individual pedigree, Parent father)
			throws PedigreeValidationError {
		if (pedigree == null || father == null)
		{
			return;
		}
		Individual fatherToAdd = createIndividual(father);
		fatherToAdd.setRelationship(RelationshipType.FATHER);
		fatherToAdd.setGender(Gender.MALE);
		pedigree.addRelation(fatherToAdd);
	}

	private void addSiblings(Individual individual,
			ArrayList<SimpleIndividual> siblings)
			throws PedigreeValidationError {
		if (individual == null || siblings == null)
		{
			return;
		}
		for (SimpleIndividual sibling : siblings)
		{
			Individual siblingToAdd = createIndividual(sibling);
			siblingToAdd.setRelationship(RelationshipType.SIBLING);
			individual.addRelation(siblingToAdd);
		}
	}

	private void addChild(Individual parent, Child child)
			throws PedigreeValidationError {
		if (child == null)
		{
			return;
		}
		Individual childToAdd = createIndividual(child);
		childToAdd.setRelationship(RelationshipType.CHILD);
		addSpouses(childToAdd, child.getSpouses());
		parent.addRelation(childToAdd);
	}

	/**
	 * @param individual
	 * @param spouses
	 * @throws PedigreeValidationError
	 * @pre
	 * @post
	 */
	private void addSpouses(Individual individual, ArrayList<Spouse> spouses)
			throws PedigreeValidationError {
		if (spouses != null)
		{
			for (Spouse spouse : spouses)
			{
				addSpouse(individual, spouse);
			}
		}
	}

	private void addSpouse(Individual individual, Spouse spouse)
			throws PedigreeValidationError {
		if (spouse == null)
		{
			return;
		}
		Individual spouseToAdd = createIndividual(spouse);
		spouseToAdd.setRelationship(RelationshipType.SPOUSE);
		addEvent(spouseToAdd, spouse.getMarriage(), "Marriage");
		addEvent(spouseToAdd, spouse.getSealing(), "Sealing");
		individual.addRelation(spouseToAdd);
	}

	public Individual createIndividual(SimpleIndividual fhdInd)
			throws PedigreeValidationError {
		if (fhdInd == null || getName(fhdInd) == null)
		{
			return null;
		}
		Individual individual = new Individual(getName(fhdInd));
		addEvent(individual, fhdInd.getBirth(), "Birth");
		addEvent(individual, fhdInd.getBurial(), "Burial");
		addEvent(individual, fhdInd.getChristening(), "Christening");
		addEvent(individual, fhdInd.getDeath(), "Death");
		if (fhdInd.isMale())
		{
			individual.setGender(Gender.MALE);
		} else
		{
			individual.setGender(Gender.UNKNOWN);
		}
		return individual;
	}

	public String getName(SimpleIndividual fhdInd) {
		if (fhdInd == null || fhdInd.getName() == null)
		{
			return null;
		}
		NameInfo nameInfo = fhdInd.getName();
		return nameInfo.getOdm_given() + " " + nameInfo.getOdm_surname();
	}

	public void addEvent(Individual pedigree,
			edu.byu.cs.dml.recordlinkage.pedigree.Event event,
			String eventNameKey) throws PedigreeValidationError {
		if (event != null)
		{
			LifeEvent occasion = new LifeEvent(getDate(event), getLocation(event));
			pedigree.addEvent(eventNameKey, occasion);
		}

	}

	public genealogy.deprecated.datamodel.pedigree.Date getDate(
			edu.byu.cs.dml.recordlinkage.pedigree.Event event) {
		if (event == null || event.getDate() == null
				|| event.getDate().getOdm_date() == null)
		{
			return null;
		}
		int day = event.getDate().getOdm_date().getDay();
		int month = event.getDate().getOdm_date().getMonth();
		int year = event.getDate().getOdm_date().getYear();
		return new genealogy.deprecated.datamodel.pedigree.Date(day, month, year);
	}

	public genealogy.deprecated.datamodel.pedigree.Location getLocation(
			edu.byu.cs.dml.recordlinkage.pedigree.Event event)
			throws PedigreeValidationError {
		if (event == null || event.getLocation() == null)
		{
			return null;
		}
		List<String> parsedLocations = new ArrayList<String>();
		for (int i = 0; i < 4; i++)
		{
			String loc = event.getLocation().getLocaction(i);
			if (loc == null || loc.length() == 0)
			{
				break;
			}
			parsedLocations.add(loc);
		}
		if (parsedLocations.size() == 0)
		{
			return null;
		}
		return new genealogy.deprecated.datamodel.pedigree.Location(parsedLocations);
	}

}
